package com.andova.toolkit.util

import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.Scheduler
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit

fun intervalTask(func: () -> Unit): Disposable {
    return Observable.interval(1L, TimeUnit.SECONDS)
            .subscribeOn(AndroidSchedulers.mainThread()).subscribe { func() }
}

fun <T> subscribeMap(map: () -> T?, next: (b: T?) -> Unit) {
    Observable.just(0).map { map() }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : Observer<T?> {
                private var d: Disposable? = null
                override fun onComplete(): Unit = run { d?.dispose() }
                override fun onSubscribe(d: Disposable) = run { this.d = d }
                override fun onNext(t: T) = run { next(t) }
                override fun onError(e: Throwable): Unit = run { d?.dispose() }
            })
}

/**
 * @see async
 */
@Deprecated("use async instead")
fun asyncMethod(func: () -> Unit, error: () -> Unit = {}) {
    Observable.just(0L)
            .observeOn(Schedulers.io())
            .subscribe(object : Observer<Long> {
                private var d: Disposable? = null
                override fun onError(e: Throwable) {
                    error()
                    d?.dispose()
                }

                override fun onSubscribe(d: Disposable) = run { this.d = d }
                override fun onNext(t: Long) {
                    func()
                }

                override fun onComplete() {
                    d?.dispose()
                }
            })
}

fun async(func: () -> Unit, error: () -> Unit = {}, scheduler: Scheduler = Schedulers.single()) {
    Observable.just(0L)
            .subscribeOn(scheduler)
            .observeOn(scheduler)
            .subscribe(object : Observer<Long> {
                private var d: Disposable? = null
                override fun onSubscribe(d: Disposable) {
                    this.d = d
                }

                override fun onError(e: Throwable) {
                    error()
                    d?.dispose()
                }

                override fun onNext(t: Long) = func()
                override fun onComplete() {
                    d?.dispose()
                }
            })
}